package ruleengine

import (
	"fmt"
	"strconv"
)

// 表达式相关内容

// 表达式接口
type Expression interface {
	Interpret(ctx *Context) interface{}
}

// 变量表达式
type VariableExpression struct {
	Name string
}

func NewVariableExpression(name string) *VariableExpression {
	return &VariableExpression{
		Name: name,
	}
}

func (e *VariableExpression) Interpret(ctx *Context) interface{} {
	return ctx.GetVariable(e.Name)
}

// 常量表达式
type ConstantExpression struct {
	Value interface{}
}

func NewConstantExpression(value interface{}) *ConstantExpression {
	return &ConstantExpression{
		Value: value,
	}
}

func (e *ConstantExpression) Interpret(ctx *Context) interface{} {
	return e.Value
}

// BinaryOperationExpression
type BinaryOperationExpression struct {
	Left     Expression
	Right    Expression
	Operator string
}

func NewBinaryOperationExpression(left, right Expression, operator string) *BinaryOperationExpression {
	return &BinaryOperationExpression{
		Left:     left,
		Right:    right,
		Operator: operator,
	}
}

func (e *BinaryOperationExpression) Interpret(ctx *Context) interface{} {
	leftVal := e.Left.Interpret(ctx)
	rightVal := e.Right.Interpret(ctx)
	// 根据运算符执行相应操作
	switch e.Operator {
	case "+":
		return add(leftVal, rightVal)
	case "-":
		return subtract(leftVal, rightVal)
	case "*":
		return multiply(leftVal, rightVal)
	case "/":
		return divide(leftVal, rightVal)
	case "==":
		return equal(leftVal, rightVal)
	case "!=":
		return notEqual(leftVal, rightVal)
	case ">":
		return greaterThan(leftVal, rightVal)
	case ">=":
		return greaterOrEqual(leftVal, rightVal)
	case "<":
		return lessThan(leftVal, rightVal)
	case "<=":
		return lessOrEqual(leftVal, rightVal)
	case "&&":
		return logicalAnd(leftVal, rightVal)
	case "||":
		return logicalOr(leftVal, rightVal)
	default:
		panic("未知运算符: " + e.Operator)
	}
	return nil
}

// FunctionCallExpression 函数调用表达式
type FunctionCallExpression struct {
	FunctionName string
	Args         []Expression
}

func NewFunctionCallExpression(functionName string, args []Expression) *FunctionCallExpression {
	return &FunctionCallExpression{
		FunctionName: functionName,
		Args:         args,
	}
}

func (e *FunctionCallExpression) Interpret(ctx *Context) interface{} {
	args := make([]interface{}, len(e.Args))
	for i, arg := range e.Args {
		args[i] = arg.Interpret(ctx)
	}
	return ctx.CallFunction(e.FunctionName, args...)
}

// ConditionalExpression 条件表达式
type ConditionalExpression struct {
	Condition   Expression
	TrueBranch  Expression
	FalseBranch Expression
}

func NewConditionalExpression(condition, trueBranch, falseBranch Expression) *ConditionalExpression {
	return &ConditionalExpression{
		Condition:   condition,
		TrueBranch:  trueBranch,
		FalseBranch: falseBranch,
	}
}

func (e *ConditionalExpression) Interpret(ctx *Context) interface{} {
	condition := e.Condition.Interpret(ctx)
	if isTruthy(condition) {
		return e.TrueBranch.Interpret(ctx)
	}
	return e.FalseBranch.Interpret(ctx)
}

// 工具函数
// 类型检查和转换工具函数
func toFloat(val interface{}) float64 {
	switch v := val.(type) {
	case int:
		return float64(v)
	case float64:
		return v
	case string:
		if f, err := strconv.ParseFloat(v, 64); err == nil {
			return f
		}
		return 0
	default:
		return 0
	}
}

func toBool(val interface{}) bool {
	switch v := val.(type) {
	case bool:
		return v
	case int, float64:
		return v != 0
	case string:
		return v != ""
	default:
		return false
	}
}

func isTruthy(val interface{}) bool {
	return toBool(val)
}

// 运算函数实现
func add(left, right interface{}) interface{} {
	leftF := toFloat(left)
	rightF := toFloat(right)
	return leftF + rightF
}

func subtract(left, right interface{}) interface{} {
	leftF := toFloat(left)
	rightF := toFloat(right)
	return leftF - rightF
}

func multiply(left, right interface{}) interface{} {
	leftF := toFloat(left)
	rightF := toFloat(right)
	return leftF * rightF
}

func divide(left, right interface{}) interface{} {
	leftF := toFloat(left)
	rightF := toFloat(right)
	if rightF == 0 {
		return 0
	}
	return leftF / rightF
}

func equal(left, right interface{}) bool {
	// 尝试数值比较
	leftF, leftIsNum := left.(float64)
	rightF, rightIsNum := right.(float64)
	if leftIsNum && rightIsNum {
		return leftF == rightF
	}

	// 尝试布尔比较
	leftB, leftIsBool := left.(bool)
	rightB, rightIsBool := right.(bool)
	if leftIsBool && rightIsBool {
		return leftB == rightB
	}

	// 默认字符串比较
	return fmt.Sprintf("%v", left) == fmt.Sprintf("%v", right)
}

func notEqual(left, right interface{}) bool {
	return !equal(left, right)
}

func greaterThan(left, right interface{}) bool {
	return toFloat(left) > toFloat(right)
}

func greaterOrEqual(left, right interface{}) bool {
	return toFloat(left) >= toFloat(right)
}

func lessThan(left, right interface{}) bool {
	return toFloat(left) < toFloat(right)
}

func lessOrEqual(left, right interface{}) bool {
	return toFloat(left) <= toFloat(right)
}

func logicalAnd(left, right interface{}) bool {
	return toBool(left) && toBool(right)
}

func logicalOr(left, right interface{}) bool {
	return toBool(left) || toBool(right)
}
